import { IDataLoadingStrategy, ILoadingContext } from './sourceLoadingStrategy';
import { MapCore } from '../mapCore';

/**
 * 分片加载策略 - 处理大数据量的分批加载
 */
export class ChunkedLoadingStrategy implements IDataLoadingStrategy {
  private readonly CHUNK_SIZE = 2000; // 每批2000个要素

  shouldUseStrategy(featureCount: number): boolean {
    return featureCount > 5000; // 大于5000个要素使用分片策略
  }

  async loadData(
    sourceId: string,
    source: mapboxgl.GeoJSONSourceSpecification,
    mapCore: MapCore,
    context?: ILoadingContext,
  ): Promise<string> {
    const { safeLog } = context || {};

    safeLog?.('🚀 启用大数据分片加载模式');
    console.time('🔍 分片加载总耗时');

    const features = (source.data as any).features;

    // 第一批：立即加载，确保地图有内容显示
    const firstChunk = features.slice(0, this.CHUNK_SIZE);
    const initialSource: mapboxgl.GeoJSONSourceSpecification = {
      type: 'geojson',
      data: {
        type: 'FeatureCollection' as const,
        features: firstChunk,
      },
    };

    console.time('🔍 首批数据加载耗时');
    const result = await mapCore.addOrUpdateSource(sourceId, initialSource);
    console.timeEnd('🔍 首批数据加载耗时');
    safeLog?.(`📊 首批加载: ${firstChunk.length} 个要素`);

    // 剩余批次：异步加载，不阻塞主线程
    if (features.length > this.CHUNK_SIZE) {
      this.loadRemainingChunksAsync(sourceId, source, mapCore, context);
    }

    console.timeEnd('🔍 分片加载总耗时');
    return result;
  }

  /**
   * 异步加载剩余数据块
   */
  private async loadRemainingChunksAsync(
    sourceId: string,
    source: mapboxgl.GeoJSONSourceSpecification,
    mapCore: MapCore,
    context?: ILoadingContext,
  ) {
    const { safeLog } = context || {};
    const features = (source.data as any).features;
    const totalChunks = Math.ceil(features.length / this.CHUNK_SIZE);

    safeLog?.(`📦 准备异步加载剩余 ${totalChunks - 1} 个数据块`);

    for (let i = 1; i < totalChunks; i++) {
      // 使用 requestIdleCallback 或 setTimeout 确保不阻塞主线程
      await new Promise<void>((resolve) => {
        const loadChunk = () => {
          console.time(`🔍 数据块${i + 1}加载耗时`);

          const end = Math.min((i + 1) * this.CHUNK_SIZE, features.length);
          const chunkFeatures = features.slice(0, end); // 累积加载

          const chunkData: GeoJSON.FeatureCollection = {
            type: 'FeatureCollection' as const,
            features: chunkFeatures,
          };

          mapCore.updateSource(sourceId, chunkData);
          console.timeEnd(`🔍 数据块${i + 1}加载耗时`);
          safeLog?.(`📊 累积加载: ${chunkFeatures.length} 个要素`);

          resolve();
        };

        // 优先使用 requestIdleCallback
        if ('requestIdleCallback' in window) {
          requestIdleCallback(loadChunk, { timeout: 1000 });
        } else {
          setTimeout(loadChunk, 16); // 约1帧的时间
        }
      });
    }

    safeLog?.('✅ 所有数据块加载完成');
  }
}
